package genesis.familytree.server.modules.common.service.impl;

import genesis.familytree.server.common.exception.GenesisException;
import genesis.familytree.server.common.persistence.Page;
import genesis.familytree.server.common.utils.StringUtils;
import genesis.familytree.server.modules.common.entity.Param;
import genesis.familytree.server.modules.common.service.IParamService;
import genesis.familytree.server.modules.common.dao.IParamDao;
import org.joda.time.LocalDate;
import org.joda.time.LocalDateTime;
import org.joda.time.LocalTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;

import static genesis.familytree.server.common.Constants.ParamCode.CAPTCHA_SYSTEM_ENABLED;

/**
 *
 */
@Transactional(readOnly = true)
@Service
public class ParamServiceImpl implements IParamService {
    private static final Logger LOG = LoggerFactory.getLogger(ParamServiceImpl.class);

    private static final DateTimeFormatter FORMATTER_DATE = DateTimeFormat.forPattern("yyyy-MM-dd");
    private static final DateTimeFormatter FORMATTER_TIME = DateTimeFormat.forPattern("HH:mm:ss");
    private static final DateTimeFormatter FORMATTER_DATE_TIME = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");

    @Resource
    private IParamDao paramDao;

    @Override
    public Param getById(int id) {
        return this.paramDao.getById(id);
    }

    @Override
    public Param getByCode(String paramCode) {
        return this.paramDao.getByCode(paramCode);
    }

    @Override
    public String getString(String paramCode) {
        Param po = this.getByCode(paramCode);
        if (null != po) {
            return po.getParamValue();
        }

        return null;
    }

    @Override
    public String getString(String paramCode, String defaultValue) {
        String value = getString(paramCode);
        if (null != value) {
            return value;
        }
        return defaultValue;
    }

    @Override
    public Double getDouble(String paramCode) {
        String value = getString(paramCode);
        try {
            value = StringUtils.trimToNull(value);
            if (StringUtils.isBlank(value)) {
                return null;
            }

            return Double.parseDouble(value);
        } catch (Exception ex) {
            LOG.error(ex.getMessage(), ex);
        }
        return null;
    }

    @Override
    public double getDouble(String paramCode, double defaultValue) {
        Double value = getDouble(paramCode);
        if (null != value) {
            return value;
        }
        return defaultValue;
    }

    @Override
    public Integer getInteger(String paramCode) {
        String value = getString(paramCode);
        try {
            value = StringUtils.trimToNull(value);
            if (StringUtils.isBlank(value)) {
                return null;
            }

            return Integer.parseInt(value);
        } catch (Exception ex) {
            LOG.error(ex.getMessage(), ex);
        }
        return null;
    }

    @Override
    public int getInteger(String paramCode, int defaultValue) {
        Integer value = getInteger(paramCode);
        if (null != value) {
            return value;
        }
        return defaultValue;
    }

    @Override
    public Boolean getBoolean(String paramCode) {
        String value = getString(paramCode);
        try {
            value = StringUtils.trimToNull(value);
            if (StringUtils.isBlank(value)) {
                return null;
            }

            if ("true".equalsIgnoreCase(value)) {
                return true;
            } else if ("false".equalsIgnoreCase(value)) {
                return false;
            } else if ("1".equalsIgnoreCase(value)) {
                return true;
            } else if ("0".equalsIgnoreCase(value)) {
                return false;
            }
        } catch (Exception ex) {
            LOG.error(ex.getMessage(), ex);
        }
        return null;
    }

    @Override
    public boolean getBoolean(String paramCode, boolean defaultValue) {
        Boolean value = getBoolean(paramCode);
        if (null != value) {
            return value;
        }
        return defaultValue;
    }

    @Override
    public BigDecimal getBigDecimal(String paramCode) {
        String value = getString(paramCode);
        try {
            value = StringUtils.trimToNull(value);
            if (StringUtils.isBlank(value)) {
                return null;
            }

            return new BigDecimal(value);
        } catch (Exception ex) {
            LOG.error(ex.getMessage(), ex);
        }
        return null;
    }

    @Override
    public BigDecimal getBigDecimal(String paramCode, BigDecimal defaultValue) {
        BigDecimal value = getBigDecimal(paramCode);
        if (null != value) {
            return value;
        }
        return defaultValue;
    }

    @Override
    public LocalDate getDate(String paramCode) {
        String value = getString(paramCode);
        try {
            value = StringUtils.trimToNull(value);
            if (StringUtils.isBlank(value)) {
                return null;
            }

            return FORMATTER_DATE.parseLocalDate(value);
        } catch (Exception ex) {
            LOG.error(ex.getMessage(), ex);
        }

        return null;
    }

    @Override
    public LocalDate getDate(String paramCode, LocalDate defaultValue) {
        LocalDate value = getDate(paramCode);
        if (null != value) {
            return value;
        }
        return defaultValue;
    }

    @Override
    public LocalTime getTime(String paramCode) {
        String value = getString(paramCode);
        try {
            value = StringUtils.trimToNull(value);
            if (StringUtils.isBlank(value)) {
                return null;
            }

            return FORMATTER_TIME.parseLocalTime(value);
        } catch (Exception ex) {
            LOG.error(ex.getMessage(), ex);
        }

        return null;
    }

    @Override
    public LocalTime getTime(String paramCode, LocalTime defaultValue) {
        LocalTime value = getTime(paramCode);
        if (null != value) {
            return value;
        }
        return defaultValue;
    }

    @Override
    public LocalDateTime getDateTime(String paramCode) {
        String value = getString(paramCode);
        try {
            value = StringUtils.trimToNull(value);
            if (StringUtils.isBlank(value)) {
                return null;
            }

            return FORMATTER_DATE_TIME.parseLocalDateTime(value);
        } catch (Exception ex) {
            LOG.error(ex.getMessage(), ex);
        }

        return null;
    }

    @Override
    public LocalDateTime getDateTime(String paramCode, LocalDateTime defaultValue) {
        LocalDateTime value = getDateTime(paramCode);
        if (null != value) {
            return value;
        }
        return defaultValue;
    }

    @Override
    public Page<Param> getPage(int pageNumber, int pageSize, Param param) {
        Page<Param> page = new Page<>(pageNumber, pageSize);

        param.setPage(page);

        List<Param> list = this.paramDao.getList(param);

        page.setList(list);

        return page;
    }

    @Transactional(readOnly = false)
    @Override
    public void saveOne(Param vo) throws GenesisException {
        boolean isNew = vo.getId() == null;
        Param po;
        if (isNew) {
            po = new Param();
            po.setIsSystem(0);
            po.setCreateBy(vo.getCreateBy());
            po.setCreateDate(vo.getCreateDate());
        }else {
            po = this.paramDao.getById(vo.getId());
            if (null == po) {
                throw new GenesisException("记录不存在");
            }
        }
        if (po.getIsSystem() == 0) {
            String paramCode = vo.getParamCode();
            Param temp = this.paramDao.getByCode(paramCode);

            if (null != temp) {
                if (!Objects.equals(temp.getId(), po.getId())) {
                    throw new GenesisException("重复的系统参数编码");
                }
            }

            po.setParamCode(paramCode);
            po.setParamName(vo.getParamName());
        }

        po.setParamValue(vo.getParamValue());
        po.setParamGroup(vo.getParamGroup());
        po.setRemarks(vo.getRemarks());
        po.setUpdateBy(vo.getUpdateBy());
        po.setUpdateDate(vo.getUpdateDate());

        if (isNew) {
            this.paramDao.saveOne(po);
        }else {
            this.paramDao.updateOne(po);
        }
    }

    @Transactional(readOnly = false)
    @Override
    public void deleteOneById(int id) {
        this.paramDao.deleteById(id);
    }
}
